#ifndef MULTICTEST_H
#define MULTICTEST_H

#include "Multiconjunto.h"
#include <iostream>
#include <string>

/**
 * Esta clase realiza los test de Multiconjunto.
*/
class MulticonjuntoTest
{
	public:
	MulticonjuntoTest();
        void StartTest (bool debug);
        void Result ();

	protected:
    	
		bool MulticonjuntoCrear();
		bool MulticonjuntoAgregaryquitar();
		bool MulticonjuntoUnion();
		bool MulticonjComparacionConConj();
		bool MulticonjAsignacionPorCopia();
	private:
		int ok;
		int error;
		
        bool d;//debug		
		MConj *m1;
		MConj *m2;
		MConj *m3;

};


MulticonjuntoTest::MulticonjuntoTest() {
	ok = 0;
	error = 0;
	m1 = new MConj ();
	m2 = new MConj ();
	m3 = new MConj ();
}
void MulticonjuntoTest::StartTest(bool debug){
    this->d=debug;
	if(MulticonjuntoCrear()){
		ok++;
	}else{
		error++;
	}
	
	if(MulticonjuntoAgregaryquitar()){
		ok++;
	}else{
		error++;
	}

	if(MulticonjuntoUnion()){
		ok++;
	}else{
		error++;
	}

	if(MulticonjComparacionConConj()){
		ok++;
	}else{
		error++;
	}

	if(MulticonjAsignacionPorCopia()){
		ok++;
	}else{
		error++;
	}

	delete m1;
	delete m2;
	delete m3;

}
void MulticonjuntoTest::Result (){
	cout << "Multiconjunto test Ok:" << ok << endl;
	cout << "Multiconjunto test cont error:" << error << endl;
};

bool MulticonjuntoTest::MulticonjuntoCrear(){

	if(d) cout << "Creé los multiconjuntos m1 m2 m3";
	if(d) cout << "Los tres multiconjuntos son vacíos? \n";
	
	if(m1->mEsVacio() && m2->mEsVacio() && m3->mEsVacio()){
		if(d) cout << "SI!\n" << endl;

	}else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoCrear:ERR" << endl;
		return false;
	}

	cout << "MCONJ::MulticonjuntoCrear:OK" << endl;
	return true;


}

bool MulticonjuntoTest::MulticonjuntoAgregaryquitar(){

	if(d) cout << "Agrego los stringuno, stringdos, stringtres a m1 \n";
	m1 -> mAgregar("stringuno");
	m1 -> mAgregar("stringdos");
	m1 -> mAgregar("stringtres");

	if(d) cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m1 << "\n";
	
	if(d) cout << "stringuno pertenece a m1? \n";
	if(m1->mPertenece("stringuno")){
		if(d) cout << "SI!\n" << endl;
	}else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(1)" << endl;
		return false;
	}

	if(d) cout << "stringdos pertenece a m1? \n";
	if(m1->mPertenece("stringdos")){
		if(d)  cout << "SI!\n" << endl;
	}else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(2)" << endl;
		return false;
	}
	if(d) cout << "stringtres pertenece a m1? \n";
	if(m1->mPertenece("stringtres")){
		if(d) cout << "SI!\n" << endl;
	}else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(3)" << endl;
		return false;
	}

	if(d) cout << "stringcuatro pertenece a m1? \n";
	if(!m1->mPertenece("stringcuatro")){
		if(d) cout << "NO!\n" << endl;
	}else {
		if(d)  cout << "SI!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(4)" << endl;
		return false;
	}

	if(d) cout<< "quito un stringuno de m1";
	m1 -> mQuitarUno("stringuno");
	if(d) cout << "Ahora m1 tiene los siguientes elementos: \n";
	if(d) cout << *m1;

	if(d) cout << "stringuno pertenece a m1? \n";
	if(!m1->mPertenece("stringuno")){
		if(d) cout << "NO!\n" << endl;
	}else {
		if(d) cout << "SI!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(5)" << endl;
		return false;
	}

	if(d) cout << "stringtres pertenece a m1? \n";
	if(m1->mPertenece("stringtres")){
		if(d) cout << "SI!\n" << endl;
	}else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(6)" << endl;
		return false;
	}
	
	if(d) cout << "ahora le agrego tres stringdos más, un \"estring\", cinco stringtres y luego nuevamente un stringdos más";
	m1 -> mAgregarN("stringdos", 3);
	m1 -> mAgregar("estring");
	m1 -> mAgregarN("stringtres", 5);	
	m1 -> mAgregar("stringdos");	

	if(d) cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m1 << "\n";

	if(d) cout << "Hay cinco stringdos en m1?\n";
	if(m1->mCantidad("stringdos") == 5){
		if(d) cout << "SI!\n" << endl;
	} else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(7)" << endl;
		return false;
	}

	if(d) cout << "Hay algún stringuno en m1?\n";
	if(m1->mCantidad("stringuno") == 0){
		if(d) cout << "NO!\n" << endl;
	} else {
		if(d) cout << "SI!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(8)" << endl;
		return false;
	}

	if(d) cout << "Ahora quito los cinco stringdos \n";
	m1->mQuitarN("stringdos", 5);
	if(d) cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m1 << "\n";
	
	if(d) cout << "Hay algún stringdos en m1?\n";
	if(m1->mCantidad("stringdos") == 0){
		if(d) cout << "NO!\n" << endl;
	} else {
		if(d) cout << "SI!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(9)" << endl;
		return false;
	}

	if(d) cout << "Ahora quito todos los demás elementos \n";
	m1 -> mQuitarN("stringtres", 6);
	m1 -> mQuitarN("estring", 1);

	if(d) cout << "Es vacío ahora m1? \n";
	
	if(m1->mEsVacio()){
		if(d) cout << "SI!\n" << endl;
	} else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(10)" << endl;
		return false;
	}
	
	if(d) cout << "Ahora le sumo cinco elementos de stringuno y de stringdos\n";
	m1 -> mAgregarN("stringuno", 5);
	m1 -> mAgregarN("stringdos", 5);
	if(d) cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m1 << "\n";
	if(d) cout << "Y los elimino directamente. \n";
	m1 -> mEliminar("stringuno");
	m1 -> mEliminar("stringdos");
	
	if(d) cout << "Es vacío ahora m1? \n";
	
	if(m1->mEsVacio()){
		if(d) cout << "SI!\n" << endl;
	} else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(11)" << endl;
		return false;
	}

	if(d) cout << "Dejo a m1 con cinco \"hola\", seis \"holgado\" y tres \"juarez\"\n";
	if(d) cout << "Dejo a m2 con cinco \"juanito\", siete \"olga\" y tres \"suarez\"\n";
	if(d) cout << "Dejo a m3 con un \"gonzalez\"\n";
	m1 -> mAgregarN("hola", 5);
	m1 -> mAgregarN("holgado", 6);
	m1 -> mAgregarN("juarez", 3);
	m2 -> mAgregarN("juanito", 5);
	m2 -> mAgregarN("olga", 7);
	m2 -> mAgregarN("suarez", 3);
	m3 -> mAgregar("gonzalez");
	

	if(d) cout << "Es vacío ahora m1? \n";

	if(!m1->mEsVacio()){
		if(d) cout << "NO!!\n" << endl;
	} else {
		if(d) cout << "SI!\n" << endl;
		cout << "MCONJ::MulticonjuntoAgregaryquitar:ERR(2)" << endl;
		return false;
	}

	if(d) cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m1 << "\n";

	if(d) cout << "Ahora m2 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m2 << "\n";

	if(d) cout << "Ahora m3 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m3 << "\n";

	cout << "MCONJ::MulticonjuntoAgregaryquitar:Ok" << endl;
	return true;


}


bool MulticonjuntoTest::MulticonjuntoUnion() {
	cout << "Esta prueba es por pantalla";
	cout << "-------------------------------------------------------" << endl;

	cout << "Hago la unión de m1 y m3 y la pongo en m2";
	m1 -> mUnion(*m3);
	*m2 = *m1;
	cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m1 << "\n";

	cout << "Ahora m2 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m2 << "\n";

	cout << "Ahora m3 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m3 << "\n";

	cout << "Ahora hago la unión de m1 y m2 (que son iguales) \n";
	m1 -> mUnion(*m2);

	cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m1 << "\n";

	cout << "Ahora m2 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m2 << "\n";

	cout << "Ahora m3 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m3 << "\n";

	cout << "Ahora hago la unión de m1 y m3";
	m1 -> mUnion(*m3);
	
	cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m1 << "\n";

	cout << "Ahora m3 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m3 << "\n";

	return true;
}

bool MulticonjuntoTest::MulticonjComparacionConConj() {

	if(d) cout << "Creo un conjunto c que tiene los elementos gonzalez, juarez, holgado";
	ConjString c;
	c.agregar("gonzalez");
	c.agregar("juarez");
	c.agregar("holgado");
	if(d) cout << "El conjunto es el siguiente, entonces: \n";
	if(d) cout << c << "\n";

	if(d) cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	if(d) cout << *m1 << "\n";

	if(d) cout << "el conjunto c tiene todos los elementos del multiconjunto m1? \n";
	if(!m1->mTieneTodos(c)){
    	if(d) 	cout << "NO!\n" << endl;
	} else {
    	if(d) 	cout << "SI!\n" << endl;
   		cout << "MCONJ::MulticonjComparacionConConj:ERR(1)" << endl;
		return false;
	}
	if(d) cout << "Y si le agrego a c \"hola\"? \n";
	c.agregar("hola");	
	if(m1->mTieneTodos(c)){ 
		if(d) cout << "SI!\n" << endl;
	} else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjComparacionConConj:ERR(2)" << endl;
		return false;
	}
	
	if(d) cout << "Y si le agrego a c \"otromas\"?\n";
	if(m1->mTieneTodos(c)){
		if(d) cout << "SI!\n" << endl;
	} else {
		if(d) cout << "NO!\n" << endl;
		cout << "MCONJ::MulticonjComparacionConConj:ERR(3)" << endl;
		return false;
	}
	cout << "MCONJ::MulticonjComparacionConConj:Ok" << endl;
	return true;	
}

bool MulticonjuntoTest:: MulticonjAsignacionPorCopia() {
	cout << "Esta prueba es por pantalla";
	cout << "-------------------------------------------------------" << endl;

	cout << "Asigno a m2, m1. \n";
	*m2 = *m1;
	
	cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m1 << "\n";

	cout << "Ahora m2 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m2 << "\n";

	cout << "Ahora le agrego a m1 2 \"hola\"\n";
	m1 -> mAgregarN("hola", 2);
	cout << "Ahora m1 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m1 << "\n";

	cout << "Ahora m2 tiene los siguientes elementos, en las siguientes cantidades: \n";
	cout << *m2 << "\n";

	return true;
}
#endif

